package org.example.infrastructure.persistent.redis;

import org.redisson.api.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Redis 服务 - Redisson
 * @author Fuzhengwei bugstack.cn @小傅哥
 */
@Service("redissonService")
public class RedissonService implements IRedisService {

    @Resource
    private RedissonClient redissonClient;

    public <T> void setValue(String key, T value) {
        redissonClient.<T>getBucket(key).set(value);
    }

    @Override
    public <T> void setValue(String key, T value, long expired) {
        RBucket<T> bucket = redissonClient.getBucket(key);
        bucket.set(value, Duration.ofMillis(expired));
    }

    public <T> T getValue(String key) {
        return redissonClient.<T>getBucket(key).get();
    }

    @Override
    public <T> RQueue<T> getQueue(String key) {
        return redissonClient.getQueue(key);
    }

    @Override
    public <T> RBlockingQueue<T> getBlockingQueue(String key) {
        return redissonClient.getBlockingQueue(key);
    }

    @Override
    public <T> RDelayedQueue<T> getDelayedQueue(RBlockingQueue<T> rBlockingQueue) {
        return redissonClient.getDelayedQueue(rBlockingQueue);
    }

    @Override
    public <K, V> RMap<K, V> getMap(String key) {
        return redissonClient.getMap(key);
    }


    @Override
    public long incr(String key) {
        return redissonClient.getAtomicLong(key).incrementAndGet();
    }

    @Override
    public long incrBy(String key, long delta) {
        return redissonClient.getAtomicLong(key).addAndGet(delta);
    }

    @Override
    public long decr(String key) {
        return redissonClient.getAtomicLong(key).decrementAndGet();
    }

    @Override
    public long decrBy(String key, long delta) {
        return redissonClient.getAtomicLong(key).addAndGet(-delta);
    }

    @Override
    public void remove(String key) {
        redissonClient.getBucket(key).delete();
    }

    @Override
    public boolean isExists(String key) {
        return redissonClient.getBucket(key).isExists();
    }

    public void addToSet(String key, String value) {
        RSet<String> set = redissonClient.getSet(key);
        set.add(value);
    }

    public boolean isSetMember(String key, String value) {
        RSet<String> set = redissonClient.getSet(key);
        return set.contains(value);
    }

    public void addToList(String key, String value) {
        RList<String> list = redissonClient.getList(key);
        list.add(value);
    }

    public String getFromList(String key, int index) {
        RList<String> list = redissonClient.getList(key);
        return list.get(index);
    }

    public void addToMap(String key, String field, String value) {
        RMap<String, String> map = redissonClient.getMap(key);
        map.put(field, value);
    }

    public Object getFromMap(String key, String field) {
        RMap<String, Object> map = redissonClient.getMap(key);
        return map.get(field);
    }

    @Override
    public String getFromStringMap(String key, String field) {
            RMap<String, String> map = redissonClient.getMap(key);
            return map.get(field);
    }

    @Override
    public Integer getFromIntegerMap(String key, String field) {
        RMap<String, Integer> map = redissonClient.getMap(key);
        return map.get(field);
    }

    public void addToSortedSet(String key, String value) {
        RSortedSet<String> sortedSet = redissonClient.getSortedSet(key);
        sortedSet.add(value);
    }

    @Override
    public RLock getLock(String key) {
        return redissonClient.getLock(key);
    }

    @Override
    public RLock getFairLock(String key) {
        return redissonClient.getFairLock(key);
    }

    @Override
    public RReadWriteLock getReadWriteLock(String key) {
        return redissonClient.getReadWriteLock(key);
    }

    @Override
    public RSemaphore getSemaphore(String key) {
        return redissonClient.getSemaphore(key);
    }

    @Override
    public RPermitExpirableSemaphore getPermitExpirableSemaphore(String key) {
        return redissonClient.getPermitExpirableSemaphore(key);
    }

    @Override
    public RCountDownLatch getCountDownLatch(String key) {
        return redissonClient.getCountDownLatch(key);
    }

    @Override
    public <T> RBloomFilter<T> getBloomFilter(String key) {
        return redissonClient.getBloomFilter(key);
    }

    @Override
    public void setMap(String key, Map<String, Integer> map) {
        // 获取 Redisson 的 RMap 对象（对应 Redis 的 Hash 结构）
        RMap<String, Integer> redisMap = redissonClient.getMap(key);
        // 清空原有数据（可选，根据业务是否需要覆盖）
        redisMap.clear();
        // 将 Java Map 中的所有键值对写入 Redis Hash
        redisMap.putAll(map);
    }

    /**
     * 指定的key，从 Redis 中查询对应的分布式原子长整型（AtomicLong）的当前值
     * 并将其作为 Long 类型返回
     * @param key
     * @return
     */
    @Override
    public Long getAtomicLong(String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        if (!atomicLong.isExists()) {
            return null; //key 不存在
        }
        return atomicLong.get();
    }

    @Override
    public void setAtomicLong(String key, Integer value) {
        redissonClient.getAtomicLong(key).set(value);
    }

    @Override
    public Boolean setNx(String key) {
        //RBucket 是 Redisson 对 Redis 字符串类型（String）的封装，可以用来存储任意类型的对象
        //当且仅当前 key 在 Redis 中不存在时，才将其值设置为 "lock"并返回 true；
        // 如果 key 已存在（无论值是什么），则不做任何操作，返回 false。
        //trySet 方法将 “判断 key 是否存在” 和 “设置值” 这两个操作合并成了一个原子操作
        return redissonClient.getBucket(key).trySet("lock");
    }

    @Override
    public Boolean setNx(String lockKey, long expireMillis, TimeUnit timeUnit) {
        return redissonClient.getBucket(lockKey).trySet("lock", expireMillis, timeUnit);
    }


}

